﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Reflection;
using System.Web.Services.Protocols;
using ApplicationGenerator.BusinessModule.Elements;

namespace ApplicationGenerator.CommonModule
{
    public class WebServiceInvoker
    {
        public void Invoke(IWebServiceInvocation webServiceInvocation, int elementId)
        {
            if (!File.Exists(WebServiceConfigurationHelper.GetPath(webServiceInvocation.WebServiceURL)))
            {
                throw new FileNotFoundException(WebServiceConfigurationHelper.GetPath(webServiceInvocation.WebServiceURL));
            }

            Assembly webServiceAssembly = Assembly.LoadFrom(WebServiceConfigurationHelper.GetPath(webServiceInvocation.WebServiceURL));
            Type webServiceType = webServiceAssembly.GetTypes().FirstOrDefault(
                (oType) =>
                {
                    return typeof(SoapHttpClientProtocol).IsAssignableFrom(oType);
                });

            if (webServiceType == null)
            {
                throw new Exception("Nie można znaleźć odpowiedniej klasy klienta dla web serwisu");
            }

            MethodInfo webServiceMethod = webServiceType.GetMethod(webServiceInvocation.MethodName);
            if (webServiceMethod == null)
            {
                throw new Exception(string.Format("Nie można znaleźć metody {}.", webServiceInvocation.MethodName));
            }

            object webServiceClient = Activator.CreateInstance(webServiceType);
            object[] methodParameters = null;
            Mappings mappings = MappingsConverterHelper.ConvertToMappings(webServiceInvocation.MappingsConfiguration);
            ElementManager elementManager = new ElementManager((new FacadeFactory()).CreateMetaModelFacade().MetaModelCollection[webServiceInvocation.MetaModelName]);
            elementManager.LoadElement(elementId);

            if (mappings.InParameteres.Count > 0)
            {
                methodParameters = new object[mappings.InParameteres.Count];

                for (int counter = 0; counter < mappings.InParameteres.Count; counter++)
                {
                    string[] pathParts = mappings.InParameteres[counter].MappedField.Split(new char[] { '.' });
                    methodParameters[counter] = elementManager.GetElement(mappings.InParameteres[counter].MappedField).GetProperty(pathParts[pathParts.Length - 1]);
                }
            }

            object returnValue = webServiceMethod.Invoke(webServiceClient, methodParameters);
            if (mappings.ReturnParameter != null)
            {
                string[] pathParts = mappings.ReturnParameter.MappedField.Split(new char[] { '.' });
                elementManager.GetElement(mappings.ReturnParameter.MappedField).SetProperty(pathParts[pathParts.Length - 1], returnValue);
            }

            elementManager.Save();
        }
    }
}
